﻿using System;
using Cpuss.Strategies;
using NUnit.Framework;

namespace Cpuss.Tests
{

    /// <summary>
    /// Tests for RepeatRunner.
    /// </summary>
    [TestFixture]
    public class RepeatRunnerTest
    {


        /// <summary>
        /// Checks to see that the number of runs that are returned are correct.
        /// </summary>
        [Test]
        public void NumberOfRunsTest()
        {
            RepeatRunner actual = new RepeatRunner(10, 20, 14, new FirstComeFirstServed(), 10, 78);

            Assert.AreEqual(10, actual.Repeat);
        }

        /// <summary>
        /// Check to see that the correct exception is raised when making less than
        /// one run.
        /// </summary>
        [Test]
        [ExpectedException(typeof(ArgumentOutOfRangeException))]
        public void NumberOfRunsLessThanTwoTest()
        {
            RepeatRunner actual = new RepeatRunner(10, 10, 10, new FirstComeFirstServed(), 1, 23);
        }

        /// <summary>
        /// Check to see that the number of std dev times is correct.
        /// </summary>
        [Test]
        public void NumberOfWaitTimeStandardDeviationsTest()
        {
            RepeatRunner actual = new RepeatRunner(10, 10, 10, new FirstComeFirstServed(), 10, 45);

            actual.Run();

            Assert.AreEqual(10, actual.WaitTimeStandardDeviations.Count);
        }

        /// <summary>
        /// Check to see that the Id of the repeat runner is not null.
        /// </summary>
        [Test]
        public void IdNotNullTest()
        {
            RepeatRunner actual = new RepeatRunner(1, 2, 3, new FirstComeFirstServed(), 3, 56);

            Assert.IsNotNull(actual.Id);
        }

        /// <summary>
        /// Check to see that the strategy string is correct.
        /// </summary>
        [Test]
        public void StrategyTest()
        {
            RepeatRunner actual = new RepeatRunner(1, 2, 3, new FirstComeFirstServed(), 2, 5);

            Assert.AreEqual("First Come First Served", actual.Strategy);
        }

        /// <summary>
        /// Check to see that the correct value is returned.
        /// </summary>
        [Test]
        public void ProcessCountTest()
        {
            RepeatRunner actual = new RepeatRunner(1, 2, 3, new FirstComeFirstServed(), 4, 3);

            Assert.AreEqual(6, actual.ProcessCount);
        }

        /// <summary>
        /// Check to see that the correct number of small processes is returned.
        /// </summary>
        [Test]
        public void SmallTest()
        {
            RepeatRunner actual = new RepeatRunner(1, 2, 3, new FirstComeFirstServed(), 3, 23);

            Assert.AreEqual(1, actual.Small);
        }

        /// <summary>
        /// Check to see that the correct number of medium processes is returned.
        /// </summary>
        [Test]
        public void MediumTest()
        {
            RepeatRunner actual = new RepeatRunner(1, 2, 3, new FirstComeFirstServed(), 6, 1);

            Assert.AreEqual(2, actual.Medium);
        }

        /// <summary>
        /// Check to see that the correct number of large processes is returned.
        /// </summary>
        [Test]
        public void LargeTest()
        {
            RepeatRunner actual = new RepeatRunner(1, 2, 3, new FirstComeFirstServed(), 3, 2);

            Assert.AreEqual(3, actual.Large);
        }

        /// <summary>
        /// Check to see that the correct exception is thrown when 
        /// </summary>
        [Test]
        [ExpectedException(typeof(ArgumentException))]
        public void SomeProcessesNeedToBeSpecifiedTest()
        {
            RepeatRunner actual = new RepeatRunner(0, 0, 0, new FirstComeFirstServed(), 4, 2);
        }

        /// <summary>
        /// Check to see that the correct exception is thrown when the value of small is a negative
        /// value.
        /// </summary>
        [Test]
        [ExpectedException(typeof(ArgumentOutOfRangeException))]
        public void SmallNegativeTest()
        {
            RepeatRunner actual = new RepeatRunner(-1, 3, 23, new FirstComeFirstServed(), 3, 2);
        }


        /// <summary>
        /// Check to see that the correct exception is thrown when the value of medium is a negative
        /// value.
        /// </summary>
        [Test]
        [ExpectedException(typeof(ArgumentOutOfRangeException))]
        public void MediumNegativeTest()
        {
            RepeatRunner actual = new RepeatRunner(0, -1, 23, new FirstComeFirstServed(), 4, 1);
        }

        /// <summary>
        /// Check to see that the correct exception is thrown when the value of large is a negative
        /// value.
        /// </summary>
        [Test]
        [ExpectedException(typeof(ArgumentOutOfRangeException))]
        public void LargeNegativeTest()
        {
            RepeatRunner actual = new RepeatRunner(0, 12, -1, new FirstComeFirstServed(), 4, 23);
        }

        /// <summary>
        /// Check to see that the correct number of % cpu utilizations is recorded.
        /// </summary>
        [Test]
        public void CpuUtilizationCountTest()
        {
            RepeatRunner actual = new RepeatRunner(1, 2, 3, new FirstComeFirstServed(), 5, 23);

            actual.Run();

            Assert.AreEqual(5, actual.CpuUtilizations.Count);
        }

        /// <summary>
        /// Check to see the correct number of turnaround times is recorded.
        /// </summary>
        [Test]
        public void TurnaroundTimesCountTest()
        {
            RepeatRunner actual = new RepeatRunner(1, 2, 3, new FirstComeFirstServed(), 5, 2);

            actual.Run();

            Assert.AreEqual(5, actual.TurnaroundTimeStandardDeviations.Count);
        }

        /// <summary>
        /// Check to see that the correct number of response times are recorded.
        /// </summary>
        [Test]
        public void ResponseTimesCountTest()
        {
            RepeatRunner actual = new RepeatRunner(1, 2, 3, new FirstComeFirstServed(), 10, 2);

            actual.Run();

            Assert.AreEqual(10, actual.ResponseTimeStandardDeviations.Count);
        }

        /// <summary>
        /// Check to see that the correct number of throughput times are recorded.
        /// </summary>
        [Test]
        public void ThroughputCountTest()
        {
            RepeatRunner actual = new RepeatRunner(10, 10, 50, new ShortestJobFirstExpert(10, 56), 10, 12);

            actual.Run();

            Assert.AreEqual(10, actual.Throughputs.Count);
        }

        /// <summary>
        /// Check to make sure the correct value is returned.
        /// </summary>
        [Test]
        public void WindowTimeFrameTest()
        {
            RepeatRunner actual = new RepeatRunner(1, 2, 3, new FirstComeFirstServed(), 10, 89);

            Assert.AreEqual(89, actual.WindowTimeframe);
        }
    }

}